---
title: "Python Asynchronous Programming"
description: "Learn Python's async programming, event loop, and async web development from a JavaScript developer's perspective."
---

## 1. Introduction

### Why Asynchronous Programming?

As a JavaScript developer, you are already familiar with concepts like Promise, async/await, and the event loop. Python also has its own async programming model, which is similar in syntax but different in underlying mechanisms.

**Core Value of Async Programming**
- Improve program performance: avoid blocking I/O operations
- Better resource utilization: handle multiple concurrent tasks in a single thread
- Responsiveness: keep the program responsive
- Scalability: support a large number of concurrent connections

> 💡 **Learning Strategy**: Think of Python's async programming as the "Python version" of the JavaScript async model

## 2. Synchronous vs Asynchronous

### 2.1 Basic Concept Comparison

<PythonEditor title="Synchronous vs Asynchronous Comparison" compare={true}>
```javascript !! js
// JavaScript synchronous operation
function syncOperation() {
    console.log("Start sync operation");
    // Simulate time-consuming operation
    const start = Date.now();
    while (Date.now() - start < 2000) {
        // Block for 2 seconds
    }
    console.log("Sync operation done");
    return "Sync result";
}

// JavaScript async operation
async function asyncOperation() {
    console.log("Start async operation");
    // Simulate async operation
    await new Promise(resolve => setTimeout(resolve, 2000));
    console.log("Async operation done");
    return "Async result";
}

// Synchronous call (will block)
console.log("Call sync function");
const syncResult = syncOperation();
console.log("Sync result:", syncResult);

// Asynchronous call (won't block)
console.log("Call async function");
asyncOperation().then(result => {
    console.log("Async result:", result);
});
console.log("Executes immediately after async call");
```

```python !! py
import asyncio
import time

# Python synchronous operation
def sync_operation():
    """Synchronous operation"""
    print("Start sync operation")
    # Simulate time-consuming operation
    time.sleep(2)  # Block for 2 seconds
    print("Sync operation done")
    return "Sync result"

# Python async operation
async def async_operation():
    """Async operation"""
    print("Start async operation")
    # Simulate async operation
    await asyncio.sleep(2)  # Non-blocking wait
    print("Async operation done")
    return "Async result"

# Synchronous call (will block)
print("Call sync function")
sync_result = sync_operation()
print("Sync result:", sync_result)

# Asynchronous call (won't block)
async def main():
    print("Call async function")
    result = await async_operation()
    print("Async result:", result)

# Run async function
print("Executes immediately after async call")
asyncio.run(main())
```
</PythonEditor>

### 2.2 Event Loop Mechanism

<PythonEditor title="Event Loop Mechanism Comparison" compare={true}>
```javascript !! js
// JavaScript event loop
console.log("1. Start execution");

setTimeout(() => {
    console.log("4. Timer callback");
}, 0);

Promise.resolve().then(() => {
    console.log("3. Promise microtask");
});

console.log("2. End of sync code");

// Output order:
// 1. Start execution
// 2. End of sync code
// 3. Promise microtask
// 4. Timer callback
```

```python !! py
import asyncio

# Python event loop
async def main():
    print("1. Start execution")
    
    # Create tasks
    task1 = asyncio.create_task(asyncio.sleep(0))
    task2 = asyncio.create_task(asyncio.sleep(0))
    
    print("2. Tasks created")
    
    # Wait for tasks to complete
    await task1
    print("3. First task done")
    
    await task2
    print("4. Second task done")

# Run event loop
asyncio.run(main())

# Output order:
# 1. Start execution
# 2. Tasks created
# 3. First task done
# 4. Second task done
```
</PythonEditor> 

## 3. Python Async Programming Basics

### 3.1 async/await Syntax

Python's async/await syntax is very similar to JavaScript, but there are some important differences.

<PythonEditor title="async/await Syntax Comparison" compare={true}>
```javascript !! js
// JavaScript async/await
async function fetchUserData(userId) {
    try {
        console.log(`Start fetching user ${userId} data`);
        // Simulate API call
        const response = await new Promise((resolve, reject) => {
            setTimeout(() => {
                if (userId > 0) {
                    resolve({
                        id: userId,
                        name: `User${userId}`,
                        email: `user${userId}@example.com`
                    });
                } else {
                    reject(new Error("User not found"));
                }
            }, 1000);
        });
        console.log("Data fetched successfully");
        return response;
    } catch (error) {
        console.error("Failed to fetch data:", error.message);
        throw error;
    }
}

async function processUsers() {
    console.log("Start processing user data");
    try {
        const user1 = await fetchUserData(1);
        const user2 = await fetchUserData(2);
        console.log("User1:", user1);
        console.log("User2:", user2);
        return [user1, user2];
    } catch (error) {
        console.error("Failed to process user data:", error.message);
    }
}

// Call async function
processUsers().then(users => {
    console.log("All users:", users);
});
```

```python !! py
import asyncio
import random

# Python async/await
async def fetch_user_data(user_id):
    """Fetch user data"""
    try:
        print(f"Start fetching user {user_id} data")
        # Simulate API call
        await asyncio.sleep(1)  # Simulate network delay
        if user_id > 0:
            data = {
                "id": user_id,
                "name": f"User{user_id}",
                "email": f"user{user_id}@example.com"
            }
            print("Data fetched successfully")
            return data
        else:
            raise ValueError("User not found")
    except Exception as error:
        print(f"Failed to fetch data: {error}")
        raise error

async def process_users():
    """Process user data"""
    print("Start processing user data")
    try:
        # Sequential execution
        user1 = await fetch_user_data(1)
        user2 = await fetch_user_data(2)
        print("User1:", user1)
        print("User2:", user2)
        return [user1, user2]
    except Exception as error:
        print(f"Failed to process user data: {error}")

# Run async function
async def main():
    users = await process_users()
    print("All users:", users)

asyncio.run(main())
```
</PythonEditor>

### 3.2 Concurrent Execution

Python provides several ways to achieve concurrent execution, similar to JavaScript's Promise.all().

<PythonEditor title="Concurrent Execution Comparison" compare={true}>
```javascript !! js
// JavaScript concurrent execution
async function fetchUserData(userId) {
    console.log(`Start fetching user ${userId} data`);
    // Simulate random delay
    const delay = 500 + Math.random() * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
    console.log(`Finished fetching user ${userId} data`);
    return {
        id: userId,
        name: `User${userId}`,
        email: `user${userId}@example.com`
    };
}

async function processUsersConcurrently() {
    console.log("Start concurrent user data fetch (Promise.all)");
    const promises = [
        fetchUserData(1),
        fetchUserData(2),
        fetchUserData(3)
    ];
    const users = await Promise.all(promises);
    console.log("All user data:", users);
    return users;
}

// Use Promise.race() to get the fastest result
async function getFastestUser() {
    console.log("\nStart race to fetch user data (Promise.race)");
    const promises = [
        fetchUserData(1),
        fetchUserData(2),
        fetchUserData(3)
    ];
    const fastestUser = await Promise.race(promises);
    console.log("Fastest user:", fastestUser);
    return fastestUser;
}

// Call functions
processUsersConcurrently();
getFastestUser();
```

```python !! py
import asyncio
import random

# Python concurrent execution
async def fetch_user_data(user_id):
    """Fetch user data"""
    print(f"Start fetching user {user_id} data")
    # Simulate random network delay
    delay = 0.5 + random.random()
    await asyncio.sleep(delay)
    print(f"Finished fetching user {user_id} data")
    return {
        "id": user_id,
        "name": f"User{user_id}",
        "email": f"user{user_id}@example.com"
    }

async def process_users_concurrently():
    """Concurrent user data processing (like Promise.all)"""
    print("Start concurrent user data fetch (asyncio.gather)")
    tasks = [
        fetch_user_data(1),
        fetch_user_data(2),
        fetch_user_data(3)
    ]
    users = await asyncio.gather(*tasks)
    print("All user data:", users)
    return users

async def get_fastest_user():
    """Get the fastest user data (like Promise.race)"""
    print("\nStart race to fetch user data (asyncio.wait)")
    tasks = [
        asyncio.create_task(fetch_user_data(1)),
        asyncio.create_task(fetch_user_data(2)),
        asyncio.create_task(fetch_user_data(3))
    ]
    # Wait for the first task to complete
    done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
    # Get the result of the completed task
    fastest_user = done.pop().result()
    # Cancel other pending tasks
    for task in pending:
        task.cancel()
    print(f"Fastest user: {fastest_user}")
    return fastest_user

# Run concurrent functions
async def main():
    await process_users_concurrently()
    await get_fastest_user()

asyncio.run(main())
```
</PythonEditor>

### 3.3 Asynchronous Context Manager

Python's async context manager is similar to JavaScript's try-with-resources pattern.

<PythonEditor title="Asynchronous Context Manager" compare={true}>
```javascript !! js
// JavaScript resource management
class AsyncResource {
    constructor(name) {
        this.name = name;
        this.isOpen = false;
    }
    async open() {
        console.log(`Open resource: ${this.name}`);
        this.isOpen = true;
    }
    async close() {
        console.log(`Close resource: ${this.name}`);
        this.isOpen = false;
    }
    async use() {
        if (!this.isOpen) {
            throw new Error("Resource not open");
        }
        console.log(`Use resource: ${this.name}`);
        await new Promise(resolve => setTimeout(resolve, 1000));
    }
}
// Manual resource management
async function useResource() {
    const resource = new AsyncResource("Database Connection");
    try {
        await resource.open();
        await resource.use();
    } finally {
        await resource.close();
    }
}
// Use resource
useResource();
```

```python !! py
import asyncio
from contextlib import asynccontextmanager

# Python async context manager
class AsyncResource:
    """Async resource class"""
    def __init__(self, name):
        self.name = name
        self.is_open = False
    async def __aenter__(self):
        print(f"Open resource: {self.name}")
        self.is_open = True
        return self
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print(f"Close resource: {self.name}")
        self.is_open = False
    async def use(self):
        if not self.is_open:
            raise RuntimeError("Resource not open")
        print(f"Use resource: {self.name}")
        await asyncio.sleep(1)

# Use async context manager
async def use_resource():
    async with AsyncResource("Database Connection") as resource:
        await resource.use()

# Use decorator to create async context manager
@asynccontextmanager
async def managed_resource(name):
    print(f"Open resource: {name}")
    try:
        yield name
    finally:
        print(f"Close resource: {name}")

async def use_managed_resource():
    async with managed_resource("File Connection") as resource:
        print(f"Use resource: {resource}")
        await asyncio.sleep(1)

# Run example
async def main():
    await use_resource()
    await use_managed_resource()

asyncio.run(main())
```
</PythonEditor> 

## 4. Async Web Development

### 4.1 FastAPI Basics

FastAPI is a modern async web framework for Python, similar to JavaScript's Express.js.

<PythonEditor title="FastAPI vs Express.js Comparison" compare={true}>
```javascript !! js
// Express.js server
const express = require('express');
const app = express();
const port = 3000;

// Middleware
app.use(express.json());

// Routes
app.get('/', (req, res) => {
    res.json({ message: 'Hello World!' });
});

app.get('/users/:id', async (req, res) => {
    try {
        const userId = parseInt(req.params.id);
        const user = await fetchUserData(userId);
        res.json(user);
    } catch (error) {
        res.status(404).json({ error: error.message });
    }
});

app.post('/users', async (req, res) => {
    try {
        const userData = req.body;
        const newUser = await createUser(userData);
        res.status(201).json(newUser);
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
});

// Start server
app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

// Simulate async functions
async function fetchUserData(userId) {
    await new Promise(resolve => setTimeout(resolve, 100));
    return { id: userId, name: `User${userId}` };
}

async function createUser(userData) {
    await new Promise(resolve => setTimeout(resolve, 100));
    return { id: Date.now(), ...userData };
}
```

```python !! py
# FastAPI server
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
import uvicorn

app = FastAPI(title="User API", version="1.0.0")

# Data models
class User(BaseModel):
    name: str
    email: str
    age: Optional[int] = None

class UserResponse(BaseModel):
    id: int
    name: str
    email: str
    age: Optional[int] = None

# Routes
@app.get("/")
async def root():
    """Root path"""
    return {"message": "Hello World!"}

@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
    """Get user"""
    try:
        user = await fetch_user_data(user_id)
        return user
    except ValueError as error:
        raise HTTPException(status_code=404, detail=str(error))

@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: User):
    """Create user"""
    try:
        new_user = await create_user_data(user)
        return new_user
    except ValueError as error:
        raise HTTPException(status_code=400, detail=str(error))

# Simulate async functions
async def fetch_user_data(user_id: int) -> UserResponse:
    """Fetch user data"""
    await asyncio.sleep(0.1)  # Simulate DB query
    if user_id <= 0:
        raise ValueError("User not found")
    return UserResponse(
        id=user_id,
        name=f"User{user_id}",
        email=f"user{user_id}@example.com",
        age=25
    )

async def create_user_data(user: User) -> UserResponse:
    """Create user data"""
    await asyncio.sleep(0.1)  # Simulate DB insert
    return UserResponse(
        id=1,  # In real apps, this should be DB-generated ID
        name=user.name,
        email=user.email,
        age=user.age
    )

# Start server
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
```
</PythonEditor>

### 4.2 Async Database Operations

<PythonEditor title="Async Database Operations" compare={true}>
```javascript !! js
// JavaScript async database operations
const { Pool } = require('pg');

class DatabaseService {
    constructor() {
        this.pool = new Pool({
            host: 'localhost',
            database: 'testdb',
            user: 'username',
            password: 'password',
            port: 5432,
        });
    }
    async getUsers() {
        const client = await this.pool.connect();
        try {
            const result = await client.query('SELECT * FROM users');
            return result.rows;
        } finally {
            client.release();
        }
    }
    async getUserById(id) {
        const client = await this.pool.connect();
        try {
            const result = await client.query(
                'SELECT * FROM users WHERE id = $1',
                [id]
            );
            return result.rows[0];
        } finally {
            client.release();
        }
    }
    async createUser(userData) {
        const client = await this.pool.connect();
        try {
            const result = await client.query(
                'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
                [userData.name, userData.email]
            );
            return result.rows[0];
        } finally {
            client.release();
        }
    }
}
// Use database service
const dbService = new DatabaseService();

async function handleGetUsers(req, res) {
    try {
        const users = await dbService.getUsers();
        res.json(users);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
}
```

```python !! py
# Python async database operations
import asyncpg
from typing import List, Optional
from pydantic import BaseModel

class User(BaseModel):
    id: Optional[int] = None
    name: str
    email: str

class DatabaseService:
    """Database service class"""
    def __init__(self):
        self.pool = None
    async def connect(self):
        """Connect to database"""
        self.pool = await asyncpg.create_pool(
            host='localhost',
            database='testdb',
            user='username',
            password='password',
            port=5432
        )
    async def close(self):
        """Close database connection"""
        if self.pool:
            await self.pool.close()
    async def get_users(self) -> List[User]:
        """Get all users"""
        async with self.pool.acquire() as conn:
            rows = await conn.fetch('SELECT * FROM users')
            return [User(**dict(row)) for row in rows]
    async def get_user_by_id(self, user_id: int) -> Optional[User]:
        """Get user by ID"""
        async with self.pool.acquire() as conn:
            row = await conn.fetchrow(
                'SELECT * FROM users WHERE id = $1',
                user_id
            )
            return User(**dict(row)) if row else None
    async def create_user(self, user: User) -> User:
        """Create user"""
        async with self.pool.acquire() as conn:
            row = await conn.fetchrow(
                'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
                user.name, user.email
            )
            return User(**dict(row))

# Use database service
db_service = DatabaseService()

async def handle_get_users():
    """Handle get users request"""
    try:
        users = await db_service.get_users()
        return users
    except Exception as error:
        raise HTTPException(status_code=500, detail=str(error))

# Use in FastAPI
@app.get("/users", response_model=List[User])
async def get_users():
    """Get all users"""
    return await handle_get_users()

@app.get("/users/{user_id}", response_model=User)
async def get_user(user_id: int):
    """Get specified user"""
    user = await db_service.get_user_by_id(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

@app.post("/users", response_model=User, status_code=201)
async def create_user(user: User):
    """Create user"""
    return await db_service.create_user(user)
```
</PythonEditor> 

## 5. Async Iteration and Generators

### 5.1 Async Iterators

<PythonEditor title="Async Iterator Comparison" compare={true}>
```javascript !! js
// JavaScript async iterator
class AsyncDataStream {
    constructor(data) {
        this.data = data;
        this.index = 0;
    }
    async *[Symbol.asyncIterator]() {
        for (const item of this.data) {
            // Simulate async processing
            await new Promise(resolve => setTimeout(resolve, 100));
            yield item;
        }
    }
}
// Use async iterator
async function processDataStream() {
    const stream = new AsyncDataStream([1, 2, 3, 4, 5]);
    for await (const item of stream) {
        console.log(`Process data: ${item}`);
    }
}
// Async generator function
async function* asyncGenerator() {
    for (let i = 0; i < 5; i++) {
        await new Promise(resolve => setTimeout(resolve, 100));
        yield i;
    }
}
async function useAsyncGenerator() {
    for await (const value of asyncGenerator()) {
        console.log(`Generated value: ${value}`);
    }
}
// Call functions
processDataStream();
useAsyncGenerator();
```

```python !! py
import asyncio

# Python async iterator
class AsyncDataStream:
    """Async data stream"""
    def __init__(self, data):
        self.data = data
        self.index = 0
    def __aiter__(self):
        return self
    async def __anext__(self):
        if self.index >= len(self.data):
            raise StopAsyncIteration
        # Simulate async processing
        await asyncio.sleep(0.1)
        item = self.data[self.index]
        self.index += 1
        return item

# Use async iterator
async def process_data_stream():
    """Process async data stream"""
    stream = AsyncDataStream([1, 2, 3, 4, 5])
    async for item in stream:
        print(f"Process data: {item}")

# Async generator function
async def async_generator():
    """Async generator"""
    for i in range(5):
        await asyncio.sleep(0.1)
        yield i

async def use_async_generator():
    """Use async generator"""
    async for value in async_generator():
        print(f"Generated value: {value}")

# Run example
async def main():
    await process_data_stream()
    await use_async_generator()

asyncio.run(main())
```
</PythonEditor>

### 5.2 Async Context Manager with Iterators

<PythonEditor title="Async Context Manager with Iterators" compare={true}>
```javascript !! js
// JavaScript async resource iterator
class AsyncFileReader {
    constructor(filename) {
        this.filename = filename;
        this.fileHandle = null;
    }
    async open() {
        this.fileHandle = await open(this.filename, 'r');
    }
    async close() {
        if (this.fileHandle) {
            await this.fileHandle.close();
        }
    }
    async *readLines() {
        if (!this.fileHandle) {
            throw new Error('File not open');
        }
        for await (const line of this.fileHandle.readLines()) {
            yield line.trim();
        }
    }
}
// Use async file reader
async function processFile(filename) {
    const reader = new AsyncFileReader(filename);
    try {
        await reader.open();
        for await (const line of reader.readLines()) {
            if (line) {
                console.log(`Process line: ${line}`);
            }
        }
    } finally {
        await reader.close();
    }
}
```

```python !! py
import asyncio
import aiofiles

# Python async file reader
class AsyncFileReader:
    """Async file reader"""
    def __init__(self, filename):
        self.filename = filename
        self.file = None
    async def __aenter__(self):
        """Enter context"""
        self.file = await aiofiles.open(self.filename, mode='r')
        return self
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """Exit context"""
        if self.file:
            await self.file.close()
    async def read_lines(self):
        """Read file lines"""
        async for line in self.file:
            yield line.strip()

# Use async file reader
async def process_file(filename):
    """Process file"""
    async with AsyncFileReader(filename) as reader:
        async for line in reader.read_lines():
            if line:
                print(f"Process line: {line}")

# Create sample file
async def create_sample_file():
    """Create sample file"""
    async with aiofiles.open('sample.txt', mode='w') as f:
        await f.write("First line\n")
        await f.write("Second line\n")
        await f.write("Third line\n")

# Run example
async def main():
    await create_sample_file()
    await process_file('sample.txt')

asyncio.run(main())
```
</PythonEditor> 

## 6. Real Project Examples

### 6.1 Async Web Crawler

<PythonEditor title="Async Web Crawler Example" compare={true}>
```javascript !! js
// JavaScript async crawler
const axios = require('axios');
const cheerio = require('cheerio');

class AsyncWebCrawler {
    constructor() {
        this.visited = new Set();
        this.results = [];
    }
    async crawlPage(url) {
        if (this.visited.has(url)) {
            return;
        }
        this.visited.add(url);
        console.log(`Crawling page: ${url}`);
        try {
            const response = await axios.get(url);
            const $ = cheerio.load(response.data);
            // Extract title
            const title = $('title').text();
            const links = $('a').map((i, el) => $(el).attr('href')).get();
            this.results.push({
                url,
                title,
                links: links.slice(0, 5) // Limit link count
            });
            console.log(`Page title: ${title}`);
        } catch (error) {
            console.error(`Crawl failed: ${url}`, error.message);
        }
    }
    async crawlMultiplePages(urls) {
        const promises = urls.map(url => this.crawlPage(url));
        await Promise.all(promises);
        return this.results;
    }
}
// Use crawler
async function main() {
    const crawler = new AsyncWebCrawler();
    const urls = [
        'https://example.com',
        'https://httpbin.org/get',
        'https://jsonplaceholder.typicode.com/posts/1'
    ];
    const results = await crawler.crawlMultiplePages(urls);
    console.log('Crawl results:', results);
}
// main();
```

```python !! py
import asyncio
import aiohttp
from bs4 import BeautifulSoup
from typing import List, Dict, Set
import time

class AsyncWebCrawler:
    """Async web crawler"""
    def __init__(self):
        self.visited: Set[str] = set()
        self.results: List[Dict] = []
    async def crawl_page(self, session: aiohttp.ClientSession, url: str):
        """Crawl single page"""
        if url in self.visited:
            return
        self.visited.add(url)
        print(f"Crawling page: {url}")
        try:
            async with session.get(url) as response:
                if response.status == 200:
                    html = await response.text()
                    soup = BeautifulSoup(html, 'html.parser')
                    # Extract title
                    title = soup.title.string if soup.title else "No title"
                    links = [a.get('href') for a in soup.find_all('a', href=True)]
                    self.results.append({
                        'url': url,
                        'title': title,
                        'links': links[:5]  # Limit link count
                    })
                    print(f"Page title: {title}")
                else:
                    print(f"HTTP error: {response.status}")
        except Exception as error:
            print(f"Crawl failed: {url} - {error}")
    async def crawl_multiple_pages(self, urls: List[str]):
        """Concurrent crawl multiple pages"""
        async with aiohttp.ClientSession() as session:
            tasks = [
                self.crawl_page(session, url) 
                for url in urls
            ]
            await asyncio.gather(*tasks)
        return self.results

# Use crawler
async def main():
    crawler = AsyncWebCrawler()
    urls = [
        'https://httpbin.org/get',
        'https://jsonplaceholder.typicode.com/posts/1',
        'https://api.github.com/users/octocat'
    ]
    start_time = time.time()
    results = await crawler.crawl_multiple_pages(urls)
    end_time = time.time()
    print(f"Crawl completed, time: {end_time - start_time:.2f} seconds")
    print("Crawl results:", results)

# Run crawler
asyncio.run(main())
```
</PythonEditor>

### 6.2 Async Task Queue

<PythonEditor title="Async Task Queue Example" compare={true}>
```javascript !! js
// JavaScript async task queue
class AsyncTaskQueue {
    constructor(concurrency = 3) {
        this.concurrency = concurrency;
        this.running = 0;
        this.queue = [];
    }
    async add(task) {
        return new Promise((resolve, reject) => {
            this.queue.push({
                task,
                resolve,
                reject
            });
            this.process();
        });
    }
    async process() {
        if (this.running >= this.concurrency || this.queue.length === 0) {
            return;
        }
        this.running++;
        const { task, resolve, reject } = this.queue.shift();
        try {
            const result = await task();
            resolve(result);
        } catch (error) {
            reject(error);
        } finally {
            this.running--;
            this.process();
        }
    }
    async waitForAll() {
        while (this.queue.length > 0 || this.running > 0) {
            await new Promise(resolve => setTimeout(resolve, 100));
        }
    }
}
// Use task queue
async function processTask(id) {
    console.log(`Start processing task ${id}`);
    await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));
    console.log(`Complete processing task ${id}`);
    return `Task ${id} result`;
}
async function main() {
    const queue = new AsyncTaskQueue(2);
    // Add tasks
    const promises = [];
    for (let i = 1; i <= 5; i++) {
        promises.push(queue.add(() => processTask(i)));
    }
    // Wait for all tasks to complete
    await queue.waitForAll();
    const results = await Promise.all(promises);
    console.log('All tasks completed:', results);
}
// main();
```

```python !! py
import asyncio
import random
from typing import List, Callable, Any
from dataclasses import dataclass

@dataclass
class Task:
    """Task class"""
    func: Callable
    args: tuple = ()
    kwargs: dict = None
    future: asyncio.Future = None
    def __post_init__(self):
        if self.kwargs is None:
            self.kwargs = {}
        if self.future is None:
            self.future = asyncio.Future()

class AsyncTaskQueue:
    """Async task queue"""
    def __init__(self, concurrency: int = 3):
        self.concurrency = concurrency
        self.running = 0
        self.queue: List[Task] = []
        self.semaphore = asyncio.Semaphore(concurrency)
    async def add(self, func: Callable, *args, **kwargs) -> asyncio.Future:
        """Add task to queue"""
        task = Task(func, args, kwargs)
        self.queue.append(task)
        asyncio.create_task(self._process_queue())
        return task.future
    async def _process_queue(self):
        """Process tasks in queue"""
        if not self.queue or self.running >= self.concurrency:
            return
        self.running += 1
        task = self.queue.pop(0)
        try:
            async with self.semaphore:
                result = await task.func(*task.args, **task.kwargs)
                task.future.set_result(result)
        except Exception as error:
            task.future.set_exception(error)
        finally:
            self.running -= 1
            if self.queue:
                asyncio.create_task(self._process_queue())
    async def wait_for_all(self):
        """Wait for all tasks to complete"""
        while self.queue or self.running > 0:
            await asyncio.sleep(0.1)

# Use task queue
async def process_task(task_id: int) -> str:
    """Process task"""
    print(f"Start processing task {task_id}")
    await asyncio.sleep(1 + random.random() * 2)
    print(f"Complete processing task {task_id}")
    return f"Task {task_id} result"

async def main():
    queue = AsyncTaskQueue(2)
    # Add tasks
    futures = []
    for i in range(1, 6):
        future = await queue.add(process_task, i)
        futures.append(future)
    # Wait for all tasks to complete
    await queue.wait_for_all()
    results = await asyncio.gather(*futures)
    print("All tasks completed:", results)

# Run task queue
asyncio.run(main())
```
</PythonEditor> 

## 7. Exercises

### Exercise 1: Async Data Processing

<PythonEditor title="Exercise 1: Async Data Processing" compare={true}>
```javascript !! js
// Async data processing exercise
async function processData(data) {
    // Simulate data processing
    await new Promise(resolve => setTimeout(resolve, 100));
    return data.map(item => item * 2);
}

async function filterData(data) {
    // Simulate data filtering
    await new Promise(resolve => setTimeout(resolve, 50));
    return data.filter(item => item > 10);
}

async function aggregateData(data) {
    // Simulate data aggregation
    await new Promise(resolve => setTimeout(resolve, 75));
    return data.reduce((sum, item) => sum + item, 0);
}

async function processDataPipeline() {
    const rawData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    console.log("Raw data:", rawData);
    // Sequential processing
    const processed = await processData(rawData);
    console.log("Processed data:", processed);
    const filtered = await filterData(processed);
    console.log("Filtered data:", filtered);
    const result = await aggregateData(filtered);
    console.log("Final result:", result);
    return result;
}

// Concurrent processing version
async function processDataConcurrently() {
    const rawData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    console.log("Raw data:", rawData);
    // Concurrent processing
    const [processed, filtered, aggregated] = await Promise.all([
        processData(rawData),
        filterData(rawData),
        aggregateData(rawData)
    ]);
    console.log("Concurrent processing results:", { processed, filtered, aggregated });
    return { processed, filtered, aggregated };
}

// Run exercise
processDataPipeline();
processDataConcurrently();
```

```python !! py
import asyncio
from typing import List

# Async data processing exercise
async def process_data(data: List[int]) -> List[int]:
    """Process data"""
    await asyncio.sleep(0.1)  # Simulate processing time
    return [item * 2 for item in data]

async def filter_data(data: List[int]) -> List[int]:
    """Filter data"""
    await asyncio.sleep(0.05)  # Simulate filtering time
    return [item for item in data if item > 10]

async def aggregate_data(data: List[int]) -> int:
    """Aggregate data"""
    await asyncio.sleep(0.075)  # Simulate aggregation time
    return sum(data)

async def process_data_pipeline():
    """Data processing pipeline (sequential processing)"""
    raw_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print("Raw data:", raw_data)
    # Sequential processing
    processed = await process_data(raw_data)
    print("Processed data:", processed)
    filtered = await filter_data(processed)
    print("Filtered data:", filtered)
    result = await aggregate_data(filtered)
    print("Final result:", result)
    return result

async def process_data_concurrently():
    """Concurrent data processing"""
    raw_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print("Raw data:", raw_data)
    # Concurrent processing
    processed, filtered, aggregated = await asyncio.gather(
        process_data(raw_data),
        filter_data(raw_data),
        aggregate_data(raw_data)
    )
    print("Concurrent processing results:", {
        "processed": processed,
        "filtered": filtered,
        "aggregated": aggregated
    })
    return {
        "processed": processed,
        "filtered": filtered,
        "aggregated": aggregated
    }

# Run exercise
async def main():
    print("=== Sequential Processing ===")
    await process_data_pipeline()
    print("\n=== Concurrent Processing ===")
    await process_data_concurrently()

asyncio.run(main())
```
</PythonEditor>

### Exercise 2: Async API Client

<PythonEditor title="Exercise 2: Async API Client" compare={true}>
```javascript !! js
// Async API client exercise
class AsyncAPIClient {
    constructor(baseURL) {
        this.baseURL = baseURL;
    }
    async get(endpoint) {
        const response = await fetch(`${this.baseURL}${endpoint}`);
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.json();
    }
    async post(endpoint, data) {
        const response = await fetch(`${this.baseURL}${endpoint}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data)
        });
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.json();
    }
    async batchGet(endpoints) {
        const promises = endpoints.map(endpoint => this.get(endpoint));
        return Promise.all(promises);
    }
}
// Use API client
async function testAPIClient() {
    const client = new AsyncAPIClient('https://jsonplaceholder.typicode.com');
    try {
        // Single request
        const user = await client.get('/users/1');
        console.log('User info:', user);
        // Batch requests
        const [posts, comments, albums] = await client.batchGet([
            '/posts/1',
            '/comments/1',
            '/albums/1'
        ]);
        console.log('Batch request results:', { posts, comments, albums });
        // POST request
        const newPost = await client.post('/posts', {
            title: 'Test article',
            body: 'This is test content',
            userId: 1
        });
        console.log('New article:', newPost);
    } catch (error) {
        console.error('API request failed:', error.message);
    }
}
// testAPIClient();
```

```python !! py
import aiohttp
import asyncio
from typing import List, Dict, Any

class AsyncAPIClient:
    """Async API client"""
    def __init__(self, base_url: str):
        self.base_url = base_url
    async def get(self, endpoint: str) -> Dict[str, Any]:
        """GET request"""
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{self.base_url}{endpoint}") as response:
                if response.status != 200:
                    raise aiohttp.ClientError(
                        f"HTTP {response.status}: {response.reason}"
                    )
                return await response.json()
    async def post(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
        """POST request"""
        async with aiohttp.ClientSession() as session:
            async with session.post(
                f"{self.base_url}{endpoint}",
                json=data
            ) as response:
                if response.status != 201:
                    raise aiohttp.ClientError(
                        f"HTTP {response.status}: {response.reason}"
                    )
                return await response.json()
    async def batch_get(self, endpoints: List[str]) -> List[Dict[str, Any]]:
        """Batch GET requests"""
        async with aiohttp.ClientSession() as session:
            tasks = [
                self._get_with_session(session, endpoint)
                for endpoint in endpoints
            ]
            return await asyncio.gather(*tasks)
    async def _get_with_session(self, session: aiohttp.ClientSession, endpoint: str):
        """GET request with existing session"""
        async with session.get(f"{self.base_url}{endpoint}") as response:
            if response.status != 200:
                raise aiohttp.ClientError(
                    f"HTTP {response.status}: {response.reason}"
                )
            return await response.json()

# Use API client
async def test_api_client():
    """Test API client"""
    client = AsyncAPIClient('https://jsonplaceholder.typicode.com')
    try:
        # Single request
        user = await client.get('/users/1')
        print('User info:', user)
        # Batch requests
        posts, comments, albums = await client.batch_get([
            '/posts/1',
            '/comments/1',
            '/albums/1'
        ])
        print('Batch request results:', {
            'posts': posts,
            'comments': comments,
            'albums': albums
        })
        # POST request
        new_post = await client.post('/posts', {
            'title': 'Test article',
            'body': 'This is test content',
            'userId': 1
        })
        print('New article:', new_post)
    except Exception as error:
        print('API request failed:', error)

# Run test
asyncio.run(test_api_client())
```
</PythonEditor> 

## 8. Summary and Extended Learning Path

Python's async programming capabilities, while starting later, are now very mature and suitable for I/O-intensive scenarios, web backends, crawlers, real-time data processing, and other fields. Through this tutorial, you have completed a comprehensive mastery from basic syntax to real projects.

### Learning Review
- Understood the usage of async/await in Python and its similarities and differences with JavaScript
- Familiarized with advanced features like event loops, concurrent execution, async generators, and context managers
- Combined FastAPI with asyncpg to implement complete async web services and database interactions
- Wrote practical async project examples like crawlers, task queues, and API clients
- Practiced real-world data processing workflows

### Recommended Extensions
Here are suggestions for further in-depth async programming learning:

#### 📚 Frameworks and Libraries
- **FastAPI**: Deep dive into dependency injection, background tasks, middleware, and other features
- **aiohttp**: Build async HTTP clients and servers
- **Starlette**: FastAPI's underlying async framework for lower-level async web services
- **Trio / Curio**: Alternative async libraries providing structured concurrency programming paradigms

#### 🛠️ Tools and Debugging
- **asyncio.TaskGroup (Python 3.11+)**: Safer concurrent execution models
- **aiomonitor / aiodebug**: Debug async event loops
- **pytest-asyncio**: Write async test cases

#### 💡 Practical Project Suggestions
- Implement an **async microservice architecture** connecting multiple async services through message queues
- Build a **WebSocket-based real-time chat room**
- Write an **async data aggregator** integrating async responses from multiple APIs

🧠 **Food for Thought**: Compared to traditional multi-threading and multi-processing programming, what are the advantages and limitations of async programming? In which real projects would you prioritize async solutions?

🎉 **Congratulations!** You have now completed a comprehensive introduction to Python async programming. If you come from a JavaScript background, you should no longer feel unfamiliar with Python's async world. Continue exploring deeper - async will become an important weapon for your development efficiency! 